import React, { useEffect, useMemo, useState } from 'react';
import lazyload from '@/utils/lazyload';
import { isArray } from '@/utils/is';
import { AuthorityResponse } from '@/constants/type';
import { IconApps, IconBulb, IconDashboard, IconSettings } from '@arco-design/web-react/icon';

export interface AuthParams {
  requiredPermissions?: Array<string>;
  oneOfPerm?: boolean;
}

export type IRoute = AuthParams & {
  name: string;
  key: string;
  icon?: React.ReactNode;
  component?: React.ReactNode;
  // 当前页是否展示面包屑
  breadcrumb?: boolean;
  children?: IRoute[];
  index?: boolean;
  // 当前路由是否渲染菜单项，为 true 的话不会在菜单中显示，但可通过路由地址访问。
  ignore?: boolean;
};

export const routes: IRoute[] = [
  {
    name: 'menu.dashboard',
    key: 'dashboard',
    icon: <IconBulb />,
    component: lazyload(() => import('./pages/dashboard/index')),
    requiredPermissions: ['dashboard']
  },
  {
    name: 'menu.alarm',
    key: 'alarm',
    icon: <IconBulb />,
    component: lazyload(() => import('./pages/alarm/index')),
    requiredPermissions: ['alarm']
  },
  {
    name: 'menu.monitor',
    key: 'monitor',
    requiredPermissions: ['monitor', 'monitor:device'],
    oneOfPerm: true,
    icon: <IconDashboard />,
    children: [
      {
        name: 'menu.monitor.device',
        key: 'monitor/index',
        component: lazyload(() => import('./pages/monitor/index')),
        requiredPermissions: ['monitor'],
        icon: <IconDashboard />,
        index: true
      },
      {
        name: 'menu.monitor.device',
        key: 'monitor/device',
        component: lazyload(() => import('./pages/monitor/device/index')),
        requiredPermissions: ['monitor:device'],
        ignore: true
      }
    ]
  },
  {
    name: 'menu.equipment',
    key: 'equipment',
    icon: <IconApps />,
    requiredPermissions: ['equipment', 'equipment:parameter', 'equipment:model', 'equipment:device'],
    oneOfPerm: true,
    children: [
      {
        name: 'menu.equipment.parameter',
        key: 'equipment/parameter',
        component: lazyload(() => import('./pages/equipment/parameter/index')),
        requiredPermissions: ['equipment:parameter']
      },
      {
        name: 'menu.equipment.model',
        key: 'equipment/model',
        component: lazyload(() => import('./pages/equipment/model/index')),
        requiredPermissions: ['equipment:model']
      },
      {
        name: 'menu.equipment.device',
        key: 'equipment/device',
        requiredPermissions: ['equipment:device', 'equipment:device:alarm_config', 'equipment:device:oee_config', 'equipment:device:utilization_config'],
        oneOfPerm: true,
        children: [
          {
            name: 'menu.equipment.device.index',
            key: 'equipment/device/index',
            component: lazyload(() => import('./pages/equipment/device/index')),
            requiredPermissions: ['equipment:device'],
            index: true
          },
          {
            name: 'menu.equipment.device.alarm_config',
            key: 'equipment/device/alarm_config',
            component: lazyload(() => import('./pages/equipment/device/AlarmConfig')),
            requiredPermissions: ['equipment:device:alarm_config'],
            ignore: true
          },
          {
            name: 'menu.equipment.device.oee_config',
            key: 'equipment/device/oee_config',
            component: lazyload(() => import('./pages/equipment/device/OeeConfig')),
            requiredPermissions: ['equipment:device:oee_config'],
            ignore: true
          },
          {
            name: 'menu.equipment.device.utilization_config',
            key: 'equipment/device/utilization_config',
            component: lazyload(() => import('./pages/equipment/device/UtilizationConfig')),
            requiredPermissions: ['equipment:device:utilization_config'],
            ignore: true
          }
        ]
      }
    ]
  },
  {
    name: 'menu.setting',
    key: 'setting',
    icon: <IconSettings />,
    requiredPermissions: ['setting', 'setting:dict', 'setting:structure', 'setting:authority', 'setting:role', 'setting:user'],
    oneOfPerm: true,
    children: [
      {
        name: 'menu.setting.dict',
        key: 'setting/dict',
        component: lazyload(() => import('./pages/setting/dict/index')),
        requiredPermissions: ['setting:dict']
      },
      {
        name: 'menu.setting.structure',
        key: 'setting/structure',
        component: lazyload(() => import('./pages/setting/structure/index')),
        requiredPermissions: ['setting:structure']
      },
      {
        name: 'menu.setting.authority',
        key: 'setting/authority',
        component: lazyload(() => import('./pages/setting/authority/index')),
        requiredPermissions: ['setting:authority']
      },
      {
        name: 'menu.setting.role',
        key: 'setting/role',
        component: lazyload(() => import('./pages/setting/role/index')),
        requiredPermissions: ['setting:role']
      },
      {
        name: 'menu.setting.user',
        key: 'setting/user',
        component: lazyload(() => import('./pages/setting/user/index')),
        requiredPermissions: ['setting:user']
      }
    ]
  }
];

export const authorization = (params: AuthParams, authorities: AuthorityResponse[]) => {
  const { requiredPermissions, oneOfPerm } = params;
  if (Array.isArray(requiredPermissions) && requiredPermissions.length) {
    const count = (requiredPermissions || []).filter(rp => (authorities || []).some((authority) => authority.code === rp)).length;
    return !!oneOfPerm ? count > 0 : count === requiredPermissions.length;
  }
  return true;
};

export const getName = (path: string, routes) => {
  return routes.find((item) => {
    const itemPath = `/${item.key}`;
    if (path === itemPath) {
      return item.name;
    } else if (item.children) {
      return getName(path, item.children);
    }
  });
};

export const useRoute = (authorities: AuthorityResponse[]): [IRoute[], string] => {
  const calculateRoutes = (routes: IRoute[]): IRoute[] => {
    const result = [];
    (routes || []).forEach(route => {
      if (authorization(route, authorities)) {
        // 计算子路由
        route.children = calculateRoutes(route.children || []);
        result.push(route);
      }
    });
    return result;
  };
  const [permissionRoute, setPermissionRoute] = useState(routes);
  useEffect(() => {
    setPermissionRoute(calculateRoutes(routes));
  }, [authorities]);

  const defaultRoute = useMemo(() => {
    const first = permissionRoute[0];
    if (first) {
      return first?.children?.[0]?.key || first.key;
    }
    return '';
  }, [permissionRoute]);

  return [permissionRoute, defaultRoute];
};

export const getFlattenRoutes = (routes: IRoute[]) => {
  const res = [];
  (routes || []).forEach((route) => {
    const visibleChildren = (route.children || []).filter(child => !child.ignore);
    if (route.key && (!route.children || !visibleChildren.length)) {
      try {
        res.push(route);
      } catch (e) {
        console.error(e);
      }
    }
    if (isArray(route.children) && route.children.length) {
      getFlattenRoutes(route.children).forEach(it => res.push(it));
    }
  });
  return res;
};

export const getRoutesByName = (routes, name) => {
  const res = [];
  (routes || []).forEach((route) => {
    if (route.name === name) {
      res.push(route);
    } else {
      if ((route.children || []).length) {
        getRoutesByName(route.children, name).forEach(it => res.push(it));
      }
    }
  });
  return res;
};
